﻿//////////////////////////////////////////////////////////////////////////////
//
//  Copyright © 1998-2024 Glodon Company Limited.  All rights reserved.
//
//  Use of this software is subject to the terms of the Glodon license
//  agreement provided at the time of installation or download, or which
//  otherwise accompanies this software in either electronic or hard copy form.  
//
//////////////////////////////////////////////////////////////////////////////

// Reviewed
#pragma once

#include "GcmpModelInterface.h"
#include "IElement.h"
#include "ElementCreationOptions.h"
#include "IVisibilityTypeFlags.h"

namespace gcmp
{
    class ICurve2d;
    class IFamily;
    class IOpeningRelationshipBehavior;
    class IElementPositionPoints;
    class IElementTransformationComponent;
    class IElementDeletionComponent;
    class IElementTrimComponent;
    class IElementAlignComponent;
    class IElementRegenerationComponent;
    class IPointArrayInstanceInput;
    class IOnePointInstanceInput;
    class IOnePointInstanceOnHostInput;
    class IPointArrayPlusHeightInstanceInput;
    class IElementUiManipulatorComponent;
    class IOpeningGraphicsElementShapeComponent;
    class IBaseGraphicsElementShapeComponent;
    class IGraphicsElementShapeCustomizableBehavior;
    class IJoinedGraphicsElementShapeComponent;
    class ISymbolGraphicsElementShapeComponent;
    class IInstanceUpdateCustomProcessor;
    class IInstanceMovablePointComponent;
    class ISubInstanceInfo;

    /// \brief 构件对象接口。
    ///
    /// 注意：如注册了属于某个专业（请见IModuleGroupManager）的外部数据（请见IExternalData），需要在创建后手动设置该Instance的所属专业
    ///       参见IBasicInformation::SetModuleGroup接口
    class GCMP_MODEL_INTERFACE_EXPORT IInstance : public IElement
    {
        DEFINE_CAST_DERIVED(gcmp::IInstance, gcmp::IElement);
    public:
        /// \brief 析构函数
        virtual ~IInstance();
#pragma region static fuction
        /// \brief 获取文档中所有构件
        /// \param pDoc 文档指针
        /// \return 返回文档中所有的构件
        static std::vector<IInstance*> GetAllInstances(const IDocument* pDoc);

        /// \brief 获取文档中所有构件Id
        /// \param pDoc 文档指针
        /// \return 返回文档中所有构件Id
        static std::vector<ElementId> GetAllInstanceIds(const IDocument* pDoc);

        /// \brief 创建构件
        ///
        /// 如果不存在名称为familyType的构件类型对象会创建一个，此创建的构件未绑定任何定位信息
        /// \param pDocment 构件文档指针
        /// \param familyId 构件的族Id
        /// \param familyType 构件的族类型名称
        /// \param name 实例名称
        /// \param canBeShared 创建的构件是否可共享
        /// \param eco Element的创建选项
        /// \param bCreateGeometryRelationshipComponent 几何关系组件是否内置创建
        /// \return 返回构件指针
        static IInstance* Create(IDocument * pDocment, const ElementId & familyId, const std::wstring & familyType, const std::wstring& name,
            bool canBeShared = true, ElementCreationOptions eco = ElementCreationOptions::Normal, bool bCreateGeometryRelationshipComponent = true);

        /// \brief 创建点式构件(勿用)
        /// 一般用于直柱这样的通过单点创建的构件。
        /// \param pInput 点式构件创建的输入数据结构
        /// \param bRegenerateInstance 构件是否更新计算数据
        /// \param bCreateGeometryRelationshipComponent 几何关系组件是否内置创建
        /// \return 返回构件指针
        static IInstance* CreateByOnePoint(const IOnePointInstanceInput* pInput, bool bRegenerateInstance = true, bool bCreateGeometryRelationshipComponent = true);

        /// \brief 创建线式构件(勿用)
        /// 一般用于墙梁这样的基础构件，通过起终点创建一个线式构件，两个点创建直线构件，三个点创建三点弧构件（点序为：起点，终点，中间点）。
        /// \param pInput 线式和多点式构件创建的输入数据结构
        /// \param bRegenerateInstance 构件是否重建
        /// \param bCreateGeometryRelationshipComponent 几何关系组件是否内置创建
        /// \return 返回构件指针
        static IInstance* CreateByPointArray(const IPointArrayInstanceInput* pInput, bool bRegenerateInstance = true, bool bCreateGeometryRelationshipComponent = true);


#pragma endregion static fuction
        /// \brief 构件嵌套到另一个族之后是否可见
        /// 这个属性主要使用在构件嵌套到另一个族中的场景。一个构件嵌套到另一个族中，把这个构件的“项目是否可见”属性，
        /// 与另一个族的族参数关联后，可以用这个新的族创建的构件的参数来控制被嵌套的构件的可见性，
        /// 比如一个门，可以通过参数控制其门把手的可见性。
        /// \return 可见这返回true，否则返回false
        virtual bool IsVisibleWhenEmbededInFamily() const = 0;
#pragma region position related

        /// \brief 设置Instance的宿主Instance的Id。
        /// \param hostInstanceId 宿主Instance的Id。
        /// \return 设置成功则返回true；否则返回false。
        virtual bool SetHostInstanceId(const ElementId& hostInstanceId) = 0;

        /// \brief 获取Instance的宿主Instance的Id。
        /// \return 返回Instance的宿主Instance的Id。
        virtual ElementId GetHostInstanceId() const = 0;

        /// \brief 设置宿主作为弱依赖。
        /// \param bHostIsWeakParent true 作为弱依赖；false 作为强依赖
        virtual void SetIsHostWeakParent(bool bIsHostWeakParent) = 0;

        /// \brief 获取宿主是否作为弱依赖。
        /// \return true 作为弱依赖；false 作为强依赖
        virtual bool IsHostWeakParent() const = 0;

        /// \brief 设置CoordinateSystemBuiltInParameter的参数值为一条曲线
        /// \param pCurve 曲线
        /// \return 是否设置成功
        virtual bool SetCoordinateSystemsByCurve(const ICurve2d* pCurve) = 0;

        /// \brief 设置CoordinateSystemBuiltInParameter的参数值为多条曲线
        /// \param curves 曲线集合
        /// \return 是否设置成功
        virtual bool SetCoordinateSystemsByCurves(const std::vector<ICurve2d*>& curves) = 0;
#pragma endregion position related

#pragma region display related

        /// \brief 获得IBaseGraphicsElementShapeComponent接口
        /// \return BaseGraphicsElementShape行为接口
        virtual const IBaseGraphicsElementShapeComponent* GetBaseGraphicsElementShapeComponent() const = 0;

        /// \brief 获得IBaseGraphicsElementShapeComponent接口
        /// \return BaseGraphicsElementShape行为接口
        virtual IBaseGraphicsElementShapeComponent* GetBaseGraphicsElementShapeComponent() = 0;

        /// \brief 获得ISymbolGraphicsElementShapeComponent接口
        /// \return SymbolGraphicsElementShapeComponent行为接口
        virtual const ISymbolGraphicsElementShapeComponent* GetSymbolGraphicsElementShapeComponent() const = 0;

        /// \brief 获得ISymbolGraphicsElementShapeComponent接口
        /// \return SymbolGraphicsElementShapeComponent行为接口
        virtual ISymbolGraphicsElementShapeComponent* GetSymbolGraphicsElementShapeComponent() = 0;

        /// \brief 标记轮廓线关联更新变化
        /// \return 
        virtual void MarkProfileRdId() = 0;

        /// \brief 判断Instance是否还在创建中
        /// \return true表示在创建中，false表示不再创建中
        virtual bool IsCreating() const = 0;

        /// \brief 获取Symbol显示数据的HolderId
        /// \return 返回一个Holder的Id。
        virtual ElementId GetSymbolGraphicsElementShapeHolderId() const = 0;

        /// \brief 获取扣减显示数据的HolderId
        /// \return 返回一个Holder的Id。
        virtual ElementId GetCutterGraphicsElementShapeHolderId() const = 0;


        /// \brief 获取Instance中与视图相关的Grep
        /// \param 当前使用的IModelView
        /// \return Instance中与视图相关的Grep
        virtual gcmp::OwnerPtr<gcmp::IGraphicsElementShape> GetModelViewGRep(const IModelView* pModelView) const = 0;

#pragma endregion display related
#pragma region family related

        /// \brief 改变族类型
        /// \param instanceTypeId 新的族类型Id
        /// \return 成功则返回true，失败则返回false。
        virtual bool ChangeTypeTo(const ElementId& instanceTypeId) = 0;

        /// \brief 获取族
        /// \return 返回族的接口指针
        virtual IFamily* GetFamily() const = 0;


#pragma endregion family related

#pragma region graphicsElementShapeCustomizableBehavior

        /// \brief 添加定制化图形行为
        /// \param opBehavior 图形定制化行为
        /// \return  返回true表示添加成功，否则表示添加失败
        virtual bool AddGraphicsElementShapeCustomizableBehavior(OwnerPtr<IGraphicsElementShapeCustomizableBehavior> opBehavior) = 0;

        /// \brief 添加定制化图形行为
        /// \param opBehavior 图形定制化行为
        /// \param moduleGroupGuid 自定义数据所属模块组
        /// \return  返回true表示添加成功，否则表示添加失败
        virtual bool AddGraphicsElementShapeCustomizableBehavior(OwnerPtr<IGraphicsElementShapeCustomizableBehavior> opBehavior, const Guid& moduleGroupGuid) = 0;

        /// \brief 清空所有定制化图形行为
        /// \return void
        virtual void ClearGraphicsElementShapeCustomizableBehaviors() = 0;

        /// \brief 获取所有定制化图形行为
        /// \return 所有定制化图形行为
        virtual const std::vector<OwnerPtr<IGraphicsElementShapeCustomizableBehavior>>& GetCustomizeGraphicsElementShapeBehaviors() const = 0;

#pragma endregion graphicsElementShapeCustomizableBehavior

#pragma region instanceMovablePointComponent
        /// \brief 获得IInstanceMovablePointComponent接口
        /// \return IInstanceMovablePointComponent行为接口
        virtual const IInstanceMovablePointComponent* GetInstanceMovablePointComponent() const = 0;

        /// \brief 获得IInstanceMovablePointComponent接口
        /// \return IInstanceMovablePointComponent行为接口
        virtual IInstanceMovablePointComponent* GetInstanceMovablePointComponent() = 0;
#pragma endregion instanceMovablePointComponent

        /// \brief 解除实例与平面的关联。
        /// 实例创建的时候默认的关联平面。可以通过这个接口解除与平面的关联。目前仅支持点式构件解除关联。
        /// \return 返回true表示解除成功，返回false表示解除不成功。
        virtual bool UnbindWithPlane() = 0;

        /// \brief 是否与平面关联。
        /// \return 返回true表示已经与平面关联，返回false表示没有与平面关联。
        virtual bool IsBoundWithPlane() const = 0;

        /// \brief 设置Element刪除组件接口
        /// \param opElementDeletionComponent 要设置的Element刪除组件
        /// \return 设置成功返回true，否则返回false
        /// \see IElementDeletionComponent
        virtual bool SetElementDeletionComponent(OwnerPtr<IElementDeletionComponent> opElementDeletionComponent) = 0;

        /// \brief 设置Instance更新时的自定义处理程序
        /// \param opInstancepdateCustomProcessor Instance更新时的自定义处理程序
        /// \return 设置成功返回true，否则返回false
        virtual bool SetInstanceUpdateCustomProcessor(OwnerPtr<IInstanceUpdateCustomProcessor> opInstancepdateCustomProcessor) = 0;

        /// \brief 设置几何关系组件(如连接、打断、扣减等关系)
        /// \param opGeometrtyRelationshipComponent 几何关系组件
        virtual void SetGeometryRelationshipComponent(OwnerPtr<IGeometryRelationshipComponent> opGeometrtyRelationshipComponent) = 0;

        /// \brief 获取可见性标记的非const指针,用户可通过操作此返回值对可见性进行修改
        ///
        /// \return 返回可见性标记的非const指针
        virtual IVisibilityTypeFlags* GetVisibilityTypeFlagsInHostDocument() = 0;

        /// \brief 获取可见性标记的const指针
        ///
        /// \return 返回可见性标记的const指针
        virtual const IVisibilityTypeFlags* GetVisibilityTypeFlagsInHostDocument() const = 0;

        /// \brief 返回构件对应的族云端版本
        ///
        /// 通常用于构件级协同下
        /// \return 构件对应的族云端版本号
        virtual Int32 GetFamilyVersionInCloud() const = 0;

        /// \brief 获取Instance所属ModelView的ElementId
        ///
        /// \return Instance所属ModelView的ElementId
        virtual const ElementId& GetHostModelViewId() const = 0;

        /// \brief 设置Instance所属ModelView的ElementId
        ///
        /// \param hostModelViewId Instance所属ModelView的ElementId
        /// \return void
        virtual void SetHostModelViewId(const ElementId& hostModelViewId) = 0;

        /// \brief 获取可见性标记
        /// 
        /// \return 标记值
        GCMP_OBSOLETE_API(2020/09/01, IInstance::GetVisibilityTypeFlagsInHostDocument() const) virtual UInt32 GetVisibilityFlag() const = 0;

        /// \brief 设置可见性标记
        /// 
        /// \param flag 标记值
        GCMP_DEPRECATED_API(2020/09/01) virtual bool SetVisibilityFlag(UInt32 flag) = 0;

#pragma region 嵌套构件相关
        /// \brief 获取Instance作为嵌套构件子实例时是否独立可见
        /// 
        /// \return 是否独立可见
        virtual bool IsIndependent() const = 0;

        /// \brief 设置Instance作为嵌套构件子实例时是否独立可见
        /// 
        /// \param isIndependent 是否独立可见
        /// \return void
        virtual void SetIndependent(bool isIndependent) = 0;

        /// \brief 获取Instance下的子构件是否要按独立属性展开创建子实例
        /// 
        /// \return 是否展开
        virtual bool ExpandSubInstances() const = 0;

        /// \brief 设置Instance下的子构件是否要按独立属性创建子实例
        /// 
        /// \param expandSubInstances 是否展开
        /// \return void
        virtual void SetExpandSubInstances(bool expandSubInstances) = 0;

        /// \brief 获取嵌套构件子构件实例的上层实例Id
        /// 
        /// 当前Instance作为嵌套构件子构件实例时，通过该接口获取上层实例Id；当前Instance并不是嵌套构件子构件实例，返回ElementId::InvaildId
        /// \return 上层实例的ElementId
        virtual ElementId GetSuperInstanceId() const = 0;

        /// \brief 获取嵌套构件子构件实例的下层实例Ids
        /// 
        /// 当前Instance作为嵌套构件子构件实例时，通过该接口获取下层实例的ElementIds；当前Instance并不是嵌套构件子构件实例，返回空容器
        /// \return 下层子构件实例的ElementIds
        virtual std::vector<ElementId> GetSubInstanceIds() const = 0;

        /// \brief 获取嵌套构件子构件实例的所有下游实例Ids
        /// 
        /// 当前Instance作为嵌套构件子构件实例时，通过该接口获取所有下游实例的ElementIds；当前Instance并不是嵌套构件子构件实例，返回空容器
        /// \return 下游子构件实例的ElementIds
        virtual std::vector<ElementId> GetAllSubInstanceIds() const = 0;

#pragma endregion 嵌套构件相关

    public:
        /// \brief 获取Implementation Uid
        ///
        /// \return UniIdentity 返回ImplementationUid
        static UniIdentity GetImplementationUid();
    };
}



